﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Windows.Forms;
using System.ComponentModel;
using XFControls.Utils;

#pragma warning disable 1591
// ReSharper disable InconsistentNaming

namespace XFControls.XFPanels.XFPanelItems
{
    public enum XFItemType
    {
        Display,
        Clickable,
        ClickableNonChange,
        Swipable
    }

    public enum XFItemClickResult
    {
        Nothing,
        SlideLeft,
        SlideRight,
        Confirm,
        CustomModal
    }

    public enum XFItemTextAlign
    {
        Left,
        Right,
        Center,
        Justified
    }

    public enum XFItemBackgroundAlign
    {
        Center,
        Stretch,
        Top,
        Bottom
    }

    public enum XFItemState
    {
        Normal,
        Disabled,
        Selected,
        SlideRight,
        SlideLeft
    }

    public class XFItemStyle : INotifyPropertyChanged, IDisposable, ICloneable
    {
        private XFItemTextAlign _TextAlign; public XFItemTextAlign TextAlign { get { return _TextAlign; } set { _TextAlign = value; RasePropertyChanged("TextAlign"); } }
        private XFItemTextAlign _SecondaryTextAlign; public XFItemTextAlign SecondaryTextAlign { get { return _SecondaryTextAlign; } set { _SecondaryTextAlign = value; RasePropertyChanged("SecondaryTextAlign"); } }

        private string _BackgroundImageString; public string BackgroundImageString { get { return _BackgroundImageString; } set { _BackgroundImageString = value; RasePropertyChanged("BackgroundImageString"); } }
        private string _SelectedBackgroundImageString; public string SelectedBackgroundImageString { get { return _SelectedBackgroundImageString; } set { _SelectedBackgroundImageString = value; RasePropertyChanged("SelectedBackgroundImageString"); } }
        private string _DisabledBackgroundImageString; public string DisabledBackgroundImageString { get { return _DisabledBackgroundImageString; } set { _DisabledBackgroundImageString = value; RasePropertyChanged("DisabledBackgroundImageString"); } }

        private Color _BackgroundColor; public Color BackgroundColor { get { return _BackgroundColor; } set { _BackgroundColor = value; RasePropertyChanged("BackgroundColor"); } }
        private Color _TextColor; public Color TextColor { get { return _TextColor; } set { _TextColor = value; RasePropertyChanged("TextColor"); } }
        private Color _SecondaryTextColor; public Color SecondaryTextColor { get { return _SecondaryTextColor; } set { _SecondaryTextColor = value; RasePropertyChanged("SecondaryTextColor"); } }
        private Font _TextFont; public Font TextFont { get { return _TextFont; } set { _TextFont = value; RasePropertyChanged("TextFont"); } }
        private Font _SecondaryTextFont; public Font SecondaryTextFont { get { return _SecondaryTextFont; } set { _SecondaryTextFont = value; RasePropertyChanged("SecondaryTextFont"); } }
        private Bitmap _BackgroundImage; public Bitmap BackgroundImage { get { return _BackgroundImage; } set { _BackgroundImage = value; RasePropertyChanged("BackgroundImage"); } }
        private XFItemBackgroundAlign _BackgroundAlign; public XFItemBackgroundAlign BackgroundAlign { get { return _BackgroundAlign; } set { _BackgroundAlign = value; RasePropertyChanged("BackgroundAlign"); } }

        private Color _SelectedBackgroundColor; public Color SelectedBackgroundColor { get { return _SelectedBackgroundColor; } set { _SelectedBackgroundColor = value; RasePropertyChanged("SelectedBackgroundColor"); } }
        private Color _SelectedTextColor; public Color SelectedTextColor { get { return _SelectedTextColor; } set { _SelectedTextColor = value; RasePropertyChanged("SelectedTextColor"); } }
        private Color _SelectedSecondaryTextColor; public Color SelectedSecondaryTextColor { get { return _SelectedSecondaryTextColor; } set { _SelectedSecondaryTextColor = value; RasePropertyChanged("SelectedSecondaryTextColor"); } }
        private Font _SelectedTextFont; public Font SelectedTextFont { get { return _SelectedTextFont; } set { _SelectedTextFont = value; RasePropertyChanged("SelectedTextFont"); } }
        private Font _SelectedSecondaryTextFont; public Font SelectedSecondaryTextFont { get { return _SelectedSecondaryTextFont; } set { _SelectedSecondaryTextFont = value; RasePropertyChanged("SelectedSecondaryTextFont"); } }
        private Bitmap _SelectedBackgroundImage; public Bitmap SelectedBackgroundImage { get { return _SelectedBackgroundImage; } set { _SelectedBackgroundImage = value; RasePropertyChanged("SelectedBackgroundImage"); } }
        private XFItemBackgroundAlign _SelectedBackgroundAlign; public XFItemBackgroundAlign SelectedBackgroundAlign { get { return _SelectedBackgroundAlign; } set { _SelectedBackgroundAlign = value; RasePropertyChanged("SelectedBackgroundAlign"); } }

        private Color _DisabledBackgroundColor; public Color DisabledBackgroundColor { get { return _DisabledBackgroundColor; } set { _DisabledBackgroundColor = value; RasePropertyChanged("DisabledBackgroundColor"); } }
        private Color _DisabledTextColor; public Color DisabledTextColor { get { return _DisabledTextColor; } set { _DisabledTextColor = value; RasePropertyChanged("DisabledTextColor"); } }
        private Color _DisabledSecondaryTextColor; public Color DisabledSecondaryTextColor { get { return _DisabledSecondaryTextColor; } set { _DisabledSecondaryTextColor = value; RasePropertyChanged("DisabledSecondaryTextColor"); } }
        private Font _DisabledTextFont; public Font DisabledTextFont { get { return _DisabledTextFont; } set { _DisabledTextFont = value; RasePropertyChanged("DisabledTextFont"); } }
        private Font _DisabledSecondaryTextFont; public Font DisabledSecondaryTextFont { get { return _DisabledSecondaryTextFont; } set { _DisabledSecondaryTextFont = value; RasePropertyChanged("DisabledSecondaryTextFont"); } }
        private Bitmap _DisabledBackgroundImage; public Bitmap DisabledBackgroundImage { get { return _DisabledBackgroundImage; } set { _DisabledBackgroundImage = value; RasePropertyChanged("DisabledBackgroundImage"); } }
        private XFItemBackgroundAlign _DisabledBackgroundAlign; public XFItemBackgroundAlign DisabledBackgroundAlign { get { return _DisabledBackgroundAlign; } set { _DisabledBackgroundAlign = value; RasePropertyChanged("DisabledBackgroundAlign"); } }

        public int Padding
        {
            set
            {
                var v = value;
                PaddingBottom = v;
                PaddingLeft = v;
                PaddingRight = v;
                PaddingTop = v;
            }
        }
        private int _PaddingTop;
        public int PaddingTop
        {
            get { return _PaddingTop; }
            set
            {
                var v = value;
                var curRes = XFGraphics.GetScreenResolution();
                if (curRes == ScreenResolution.QVGA || curRes == ScreenResolution.RotatedQVGA || curRes == ScreenResolution.Unknown)
                    v /= 2;
                _PaddingTop = v;
                RasePropertyChanged("PaddingTop");
            }
        }
        private int _PaddingBottom;
        public int PaddingBottom
        {
            get { return _PaddingBottom; }
            set
            {
                var v = value;
                var curRes = XFGraphics.GetScreenResolution();
                if (curRes == ScreenResolution.QVGA || curRes == ScreenResolution.RotatedQVGA || curRes == ScreenResolution.Unknown)
                    v /= 2;

                _PaddingBottom = v;
                RasePropertyChanged("PaddingBottom");
            }
        }
        private int _PaddingLeft;
        public int PaddingLeft
        {
            get { return _PaddingLeft; }
            set
            {
                var v = value;
                var curRes = XFGraphics.GetScreenResolution();
                if (curRes == ScreenResolution.QVGA || curRes == ScreenResolution.RotatedQVGA || curRes == ScreenResolution.Unknown)
                    v /= 2;

                _PaddingLeft = v;
                RasePropertyChanged("PaddingLeft");
            }
        }
        private int _PaddingRight;
        public int PaddingRight
        {
            get { return _PaddingRight; }
            set
            {
                var v = value;
                var curRes = XFGraphics.GetScreenResolution();
                if (curRes == ScreenResolution.QVGA || curRes == ScreenResolution.RotatedQVGA || curRes == ScreenResolution.Unknown)
                    v /= 2;

                _PaddingRight = v;
                RasePropertyChanged("PaddingRight");
            }
        }

        public DashStyle DashStyleTop { get { return _dashStyleTop; } set { _dashStyleTop = value; BorderTop = true; RasePropertyChanged("Border"); } }
        public DashStyle DashStyleBottom { get { return _dashStyleBottom; } set { _dashStyleBottom = value; BorderBottom = true; RasePropertyChanged("Border"); } }
        public DashStyle DashStyleLeft { get { return _dashStyleLeft; } set { _dashStyleLeft = value; BorderLeft = true; RasePropertyChanged("Border"); } }
        public DashStyle DashStyleRight { get { return _dashStyleRight; } set { _dashStyleRight = value; BorderRight = true; RasePropertyChanged("Border"); } }

        private DashStyle _dashStyleTop;
        private DashStyle _dashStyleBottom;
        private DashStyle _dashStyleLeft;
        private DashStyle _dashStyleRight;

        public bool BorderTop { get; private set; }
        public bool BorderBottom { get; private set; }
        public bool BorderLeft { get; private set; }
        public bool BorderRight { get; private set; }

        private Color _BorderTopColor; public Color BorderTopColor { get { return _BorderTopColor; } set { _BorderTopColor = value; RasePropertyChanged("BorderTopColor"); } }
        private Color _BorderBottomColor; public Color BorderBottomColor { get { return _BorderBottomColor; } set { _BorderBottomColor = value; RasePropertyChanged("BorderBottomColor"); } }
        private Color _BorderLeftColor; public Color BorderLeftColor { get { return _BorderLeftColor; } set { _BorderLeftColor = value; RasePropertyChanged("BorderLeftColor"); } }
        private Color _BorderRightColor; public Color BorderRightColor { get { return _BorderRightColor; } set { _BorderRightColor = value; RasePropertyChanged("BorderRightColor"); } }

        public XFItemStyle()
        {
            BorderBottomColor = Color.Black;
            BorderLeftColor = Color.Black;
            BorderRightColor = Color.Black;
            BorderTopColor = Color.Black;
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (TextFont != null)
                TextFont.Dispose();
            if (SecondaryTextFont != null)
                SecondaryTextFont.Dispose();
            if (BackgroundImage != null)
                BackgroundImage.Dispose();
            if (SelectedTextFont != null)
                SelectedTextFont.Dispose();
            if (SelectedSecondaryTextFont != null)
                SelectedSecondaryTextFont.Dispose();
            if (SelectedBackgroundImage != null)
                SelectedBackgroundImage.Dispose();
            if (DisabledTextFont != null)
                DisabledTextFont.Dispose();
            if (DisabledSecondaryTextFont != null)
                DisabledSecondaryTextFont.Dispose();
            if (DisabledBackgroundImage != null)
                DisabledBackgroundImage.Dispose();
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void RasePropertyChanged(string prop)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }

        #endregion

        #region ICloneable Members

        public object Clone()
        {
            var ret = (XFItemStyle)Activator.CreateInstance(GetType());

            foreach (MemberInfo member in GetType().GetMembers())
            {
                if (member is FieldInfo)
                {
                    FieldInfo field = (FieldInfo)member;
                    if (field.FieldType == typeof(Font))
                    {
                        var curFont = (Font)field.GetValue(this);
                        if (curFont == null) continue;
                        Font f = new Font(curFont.Name, curFont.Size, curFont.Style);
                        field.SetValue(ret, f);
                    }
                    else
                        field.SetValue(ret, field.GetValue(this));
                }
                else if (member is PropertyInfo)
                {
                    PropertyInfo field = (PropertyInfo)member;
                    if (field.Name == "Padding")
                        continue;

                    if (field.PropertyType == typeof(Font))
                    {
                        var curFont = (Font)field.GetValue(this, new object[] { });
                        if (curFont == null) continue;
                        Font f = new Font(curFont.Name, curFont.Size, curFont.Style);
                        field.SetValue(ret, f, new object[] { });
                    }
                    else
                        field.SetValue(ret, field.GetValue(this, new object[] { }), new object[] { });
                }
            }
            return ret;
        }

        #endregion
    }

    public interface IXFItem : IDisposable
    {
        event EventHandler<EventArgs> Click;
        event EventHandler<EventArgs> Change;
        event EventHandler<EventArgs> ScreenResize;
        event EventHandler<EventArgs> MouseUp;
        event EventHandler<MouseEventArgs> MouseDown;
        event EventHandler<MouseEventArgs> MouseMove;
        event EventHandler<EventArgs> Focus;
        event EventHandler<EventArgs> Blur;
        event EventHandler<EventArgs> Refresh;
        event EventHandler<EventArgs> Disposed;
        event EventHandler<EventArgs> Draw;
        event EventHandler<EventArgs> Add;

        XFPanelBase Parent { get; set; }
        XFItemState State { get; set; }
        Bitmap Buffer { get; set; }
        XFItemStyle Style { get; set; }
        XFItemType ItemType { get; set; }
        bool Visible { get; set; }
        bool Animated { get; set; }
        bool Rendered { get; set; }
        Rectangle ItemRectangle { get; set; }
        object Tag { get; set; }

        void ItemPaint(Graphics g, int x, int y);

        int GetHeight();
        int GetWidth();
        void ResetHeight();

        XFItemClickResult GetClickResult();
        void OnMouseDown(int x, int y);
        void OnMouseMove(int x, int y);
        void OnMouseUp();
        void OnFocus();
        void OnBlur();
        void OnScreenResize();
        void OnRefresh();
        void Invalidate();
        void Deflate();
        void Invalidate(bool invalParent);
        void OnAdd();

        IXFItem GetCopy();
    }

    public interface IXFItemContainer : IXFItem
    {
        List<IXFItem> GetItems();
    }

    public interface IXFItemExpandable : IXFItem
    {
        void SetHeight(int ammount);
    }

    public interface IXFItemSwipeable : IXFItem
    {
        void Swipe(Point Start, Point End);
    }

    public interface IXFIcon
    {
        int Number { get; set; }
        XFPanelIcon Parent { get; set; }
        int Width { get; set; }
        int Height { get; set; }
        bool Selected { get; set; }
        Rectangle ImageRectange { get; set; }
        bool IsEmpty { get; set; }
        string Icon { get; }

        void PaintIcon(Graphics g, int x, int y);
        IXFIcon GetCopy();
        void OnClick();
    }

    public class XFIcon : IXFIcon
    {
        public event EventHandler<EventArgs> Click;
        public Color TextColor = Color.Black;
        public Rectangle ImageRectange { get; set; }
        public int Number { get; set; }
        public XFPanelIcon Parent { get; set; }

        private const int padding = 5;
        private string _text;

        public int Width { get; set; }
        public int Height { get; set; }
        public bool Selected { get; set; }
        public string Icon { get; private set; }

        public XFIcon(string text, string icon)
        {
            _text = text;
            Icon = icon;
        }

        public bool IsEmpty { get; set; }

        public void PaintIcon(Graphics g, int x, int y)
        {
            var font = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular);

            Rectangle textRec = new Rectangle(x + padding, y, Width - (padding << 1), 0);
            var textSize = font.MeasureString(_text, textRec);
            int iconWidth = Width - (padding << 1);
            int iconHeight = Height - (padding << 1) - textSize.Height;

            iconHeight = Math.Min(iconHeight, iconWidth);
            textRec.Y += iconHeight + padding;
            textRec.Height = textSize.Height;

            ImageRectange = new Rectangle(x + ((Width >> 1) - (iconHeight >> 1)), y + padding, iconHeight, iconHeight);
            g.DrawRoundedRectangleBorderImageFill(this, Icon, Color.FromArgb(120, 125, 128), ImageRectange, iconHeight >> 2, 3, XFGraphicExtensions.RoundedCorners.All);
            g.DrawString(_text, textRec, XFItemTextAlign.Center, font, TextColor);
        }

        public void OnClick()
        {
            if (Click != null)
                Click(this, new EventArgs());
        }

        public IXFIcon GetCopy()
        {
            return MemberwiseClone() as IXFIcon;
        }
    }

    public class XFItemBack : XFItemBase
    {
        private int height = 40;

        public XFItemBack()
        {
            Style = new XFItemStyle
                    {
                        PaddingTop = 2,
                        BackgroundColor = Color.RoyalBlue,
                        TextFont = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Bold),
                        TextColor = Color.White,
                        DashStyleBottom = DashStyle.Dash
                    };

            ItemType = XFItemType.Clickable;
        }

        public override int GetHeight()
        {
            return height + Style.PaddingTop + Style.PaddingBottom;
        }

        public override void ResetHeight() { }

        public override void ItemPaint(Graphics g, int x, int y)
        {
            int width = GetWidth();
            string loading = "Back";

            XFControlUtils.DrawBackground(this, Style, g, x, y, width, GetHeight());
            XFControlUtils.DrawBorders(Style, g, x, y, width, GetHeight());

            int xmid = width / 2;

            using (SolidBrush b = new SolidBrush(Style.TextColor))
            {
                xmid -= (int)(g.MeasureString(loading, Style.TextFont).Width / 2);
                g.DrawString(loading, Style.TextFont, b, xmid, y + Style.PaddingTop);
            }
        }

        public override XFItemClickResult GetClickResult()
        {
            if (Parent == null)
                return XFItemClickResult.Nothing;

            return XFItemClickResult.SlideRight;
        }
    }

    public class XFItemBackHeader : XFItemBack
    {
        public XFItemBackHeader()
        {
            ItemType = XFItemType.Display;
            Style = new XFItemStyle();
        }

        public new XFPanelBase Parent
        {
            get { return _parent; }
            set
            {
                _parent = value;
                if (_parent.Parent != null && _parent.Parent is XFPanelContainer)
                {
                    var cont = _parent.Parent as XFPanelContainer;
                    cont.SetHeaderLeftButton(new XFButtonBack());
                }
            }
        }
        private XFPanelBase _parent;

        public override int GetHeight()
        {
            return 0;
        }

        public override void ItemPaint(Graphics g, int x, int y) { }

        public override XFItemClickResult GetClickResult()
        {
            return XFItemClickResult.SlideRight;
        }
    }
}

// ReSharper restore InconsistentNaming
#pragma warning restore 1591
